/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.upf.grupoe.p2ppicture.Image.Implementations;

import com.sun.media.jai.codec.JPEGEncodeParam;
import java.awt.RenderingHints;
import java.awt.image.renderable.ParameterBlock;
import javax.media.jai.*;
import javax.media.jai.operator.GradientMagnitudeDescriptor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * @author marc
 */
public class EditorImpl {
    private String filename = "";
    private PlanarImage input = null;
    private PlanarImage output = null;
    
    private static Log logger = LogFactory.getLog("Main");
        
    public void saveJPEGQuality(String outputfilename, float quality){
            try{
                JPEGEncodeParam params = new JPEGEncodeParam();
                params.setQuality(quality);
                JAI.create("filestore",output,outputfilename,"JPEG",params);
            }
            catch(Exception e){
                System.err.println("Error saving a JPEG picture");
            }
    }
    
    public void loadImage(String filename){
       input = JAI.create("fileload", filename);
       output = input;
       System.gc();
    }
    
    public void saveImage(String outputName, String fileType){
         if(logger.isDebugEnabled()){
            logger.info("Name: "+outputName + "FT: "+fileType);
         }
        JAI.create("filestore", output, outputName, fileType);
        System.gc();
    }
    /**
     * Resizes de image given x and y float factors
     * @param xScale
     * @param yScale 
     */
    public void changeSize(float xScale, float yScale){
        // Create a ParameterBlock and specify the source and
        // parameters
        ParameterBlock pb = new ParameterBlock();
            pb.addSource(output);                   // The source image
            pb.add(xScale);                        // The xScale
            pb.add(yScale);                        // The yScale
            pb.add(0.0F);                       // The x translation
            pb.add(0.0F);                       // The y translation
            pb.add(new InterpolationNearest()); // The interpolation
        // Create the scale operation
        output = JAI.create("scale", pb, null);
    }
    /**
     * Blurs the image applying a Gaussian filtering with a grade(3-5-7-9)
     * @param grade 
     */
    public void blurring(int grade){
        // Lowpass filter creation
        int kernelSize = grade;
        float[] kernelMatrix = new float[kernelSize*kernelSize];
        for(int k=0;k<kernelMatrix.length;k++){
            kernelMatrix[k] = 1.0f/(grade*grade);
        }
        KernelJAI kernel = new KernelJAI(kernelSize,kernelSize,kernelMatrix);
	// Convolution
       
        RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));
        
	output = JAI.create("Convolve", output, kernel, hint);
    }
    public void sharpening(){   
        float[] filterSmooth = { 1.0F/9.0F, 1.0F/9.0F, 1.0F/9.0F,1.0F/9.0F, 1.0F/9.0F, 1.0F/9.0F, 1.0F/9.0F, 1.0F/9.0F, 1.0F/9.0F};
        KernelJAI kernelSmooth = new KernelJAI(3,3,filterSmooth);
        RenderingHints hint = new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY));
        float[] filter = { -1.0F, -1.0F, -1.0F,-1.0F, 9.0F, -1.0F, -1.0F, -1.0F, -1.0F};
        KernelJAI kernel = new KernelJAI(3,3,filter);    
        // Noise reduction. Pre-emphasis filter
        output = JAI.create("Convolve", output, kernelSmooth, hint);
        // Laplacian fitler
        output = JAI.create("Convolve", output, kernel, hint);
        
         
    }
    public void rotating(float degrees){
       float angle = (float)Math.toRadians(degrees);  
       float centerX = output.getWidth()/2f;  
       float centerY = output.getHeight()/2f;  
       ParameterBlock pb = new ParameterBlock();  
       pb.addSource(output);  
       pb.add(centerX);  
       pb.add(centerY);  
       pb.add(angle);  
       pb.add(new InterpolationBilinear());  
       output = JAI.create("rotate", pb);  
    }
    /**
     * A value from 0.5 to 1.25
     * @param A 
     */
    public void changeContrast(float A){
        int numBands = input.getNumBands();
        float[][][] bp = new float[numBands][2][];
        for(int b = 0; b < numBands; b++) {
            bp[b][0] = new float[] {0.0F, 64.0F, 128.0F, 192.0F, 255.0F};
            bp[b][1] = new float[] {0.0F, A*64.0F, A*128.0F, A*192.0F, 255.0F};
        }
        // Create the Piecewise operation.
        output = JAI.create("piecewise", output, bp);
    }
    public void setFilename(String f){
        filename = f;
    }
    
    public PlanarImage getInput(){
        return input;
    }
    
    public PlanarImage getOutput(){
        return output;
    }
    
    public void setInput(PlanarImage im){
        input = im;
    }
    public void setOutput(PlanarImage im){
        output = im;
    }
}